package com.ourteam.frame.web;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

import net.ui.UIConfigFactory;
import net.ui.model.tree.NodeBean;
import net.ui.model.tree.SubNodeBuilderBean;
import net.ui.model.tree.TreeBean;
import net.ui.model.tree.TreeNodeBean;

public abstract class AbstractTreeBuilder implements Serializable {

	private TreeBean treeConfig;

	protected Object getParentId(Object parentObject) {
		String[] array = StringUtils.split(String.valueOf(parentObject), "-",2);
		if (array.length == 1) {
			return parentObject;
		} else {
			return array[1];
		}
	}

	protected boolean isShowTag() {
		return false;
	}

	public TreeViewNodeBean[] getTreeGrid(Object parentObject, int nodeLevel, String nodeConfigId) throws Exception {

		treeConfig = UIConfigFactory.getInstance(getTreeConfigFile()).getTreeConfig(getTreeConfigFile());
		
		if(treeConfig == null) {
			throw new Exception("can not found tree config file : " + getTreeConfigFile());
		}

		if (StringUtils.isEmpty(nodeConfigId)) {

			List<TreeNodeBean> rootNodeBeans = treeConfig.getRootNodeList();

			TreeViewNodeBean[] treeViewNodeBeans = null;

			for (Iterator<TreeNodeBean> iterator = rootNodeBeans.iterator(); iterator.hasNext();) {

				TreeNodeBean treeNodeBean = iterator.next();

				NodeBean nodeConfig = treeConfig.getNodeDefine(treeNodeBean.getId());

				if (treeViewNodeBeans == null) {
					treeViewNodeBeans = buildTreeNode(getParentId(parentObject), nodeLevel, nodeConfig);
				} else {
					treeViewNodeBeans = (TreeViewNodeBean[]) ArrayUtils.addAll(treeViewNodeBeans,
							buildTreeNode(getParentId(parentObject), nodeLevel, nodeConfig));
				}

			}

			return treeViewNodeBeans;

		} else {

			NodeBean nodeConfig = treeConfig.getNodeDefine(nodeConfigId);

			return buildTreeNode(getParentId(parentObject), nodeLevel, nodeConfig);
		}

	}

	protected TreeViewNodeBean[] buildTreeNode(Object parentObject, int nodeLevel, NodeBean nodeConfig)
			throws Exception {

		SubNodeBuilderBean[] subNodeBuilderBeans = nodeConfig.getSubNodBuilders();

		List<TreeViewNodeBean> treeViewNodeBeans = new ArrayList<TreeViewNodeBean>();

		for (int i = 0; i < subNodeBuilderBeans.length; i++) {

			SubNodeBuilderBean subNodeBuilderBean = subNodeBuilderBeans[i];

			String subNodeBuilderClassName = subNodeBuilderBean.getClassName();

			Class subNodeBuilderClass = Class.forName(subNodeBuilderClassName);

			ITreeNodeBuilder treeNodeBuilder = (ITreeNodeBuilder) subNodeBuilderClass.newInstance();

			initTreeNodeBuilder(treeNodeBuilder);

			Object[] childObjects = treeNodeBuilder
					.getTreeNodeObjects(treeNodeBuilder.converToParentObject(parentObject));

			for (int j = 0; j < childObjects.length; j++) {

				Object object = childObjects[j];

				NodeBean childNodeBean = treeConfig.getNodeDefine(treeNodeBuilder.getNodeDefineId(object));

				TreeViewNodeBean treeViewNodeBean = getTreeViewNodeBean(treeNodeBuilder, parentObject, object,
						nodeConfig, childNodeBean, nodeLevel);

				treeViewNodeBean.setShowTag(isShowTag());

				treeViewNodeBeans.add(treeViewNodeBean);
			}
		}

		return (TreeViewNodeBean[]) treeViewNodeBeans.toArray(new TreeViewNodeBean[treeViewNodeBeans.size()]);

	}

	abstract protected String getTreeConfigFile();

	protected void initTreeNodeBuilder(ITreeNodeBuilder treeNodeBuilder) throws Exception {

	}

	protected TreeViewNodeBean getTreeViewNodeBean(ITreeNodeBuilder treeNodeBuilder, Object parentObject, Object object,
			NodeBean nodeConfig, NodeBean childNodeBean, int nodeLevel) throws Exception {

		TreeViewNodeBean treeViewNodeBean = new TreeViewNodeBean();

		treeViewNodeBean.setNodeConfigId(childNodeBean.getId());

		treeViewNodeBean.getState().setExpanded(false);

		treeViewNodeBean.setLevel(nodeLevel + 1);

		if (nodeLevel == 0) {
			treeViewNodeBean.setParent(null);
		} else {
			treeViewNodeBean.setParent(nodeConfig.getId() + "-" + String.valueOf(parentObject));
		}

		//treeViewNodeBean.setChildCount(treeNodeBuilder.getChildCount(object));
		
		String tag = treeNodeBuilder.getTag(object);
		
		if(StringUtils.isNotBlank(tag)){
			treeViewNodeBean.setTags(new String[]{tag});
		}

		treeViewNodeBean.setIsLeaf(treeNodeBuilder.isLeaf(object));

		if (PropertyUtils.isReadable(object, childNodeBean.getImage())) {
			treeViewNodeBean.setIcon(String.valueOf(PropertyUtils.getProperty(object, childNodeBean.getImage())));
		} else {
			treeViewNodeBean.setIcon(childNodeBean.getImage());
		}

		if (StringUtils.isNotBlank(childNodeBean.getLabel())
				&& PropertyUtils.isReadable(object, childNodeBean.getLabel())) {
			treeViewNodeBean.setText(String.valueOf(PropertyUtils.getProperty(object, childNodeBean.getLabel())));
		}
		else {
			treeViewNodeBean.setText(childNodeBean.getLabel());
		}

		treeViewNodeBean.setNodeData(object);

		treeViewNodeBean.setId(childNodeBean.getId() + "-" + String.valueOf(treeNodeBuilder.getNodeId(object)));

		treeViewNodeBean = configTreeViewNodeProperties(object, treeViewNodeBean);

		return treeViewNodeBean;
	}

	protected TreeViewNodeBean configTreeViewNodeProperties(Object obj, TreeViewNodeBean treeViewNodeBean) {
		return treeViewNodeBean;
	}
}
